package com.igbeok.miscellaneous.concurrency.hemberg;

import java.util.Random;

public class Customer implements Runnable {
	// 顾客要面对服务生
	Waiter waiter;
	// 也要面对汉堡包容器
	HambergFifo pool;
	// 想要记下自己吃了多少汉堡
	int ateCount = 0;
	// 吃每个汉堡的时间不尽相同
	long sleeptime;
	// 用于产生随机数
	Random r = new Random();

	public Customer(Waiter waiter, HambergFifo pool) {
		this.waiter = waiter;
		this.pool = pool;
	}

	public void run() {

		while (true) {

			try {
				// 取汉堡
				getHamberg();
				// 吃汉堡
				eatHamberg();
			} catch (Exception e) {
				synchronized (waiter) {
					System.out.println(e.getMessage());
					// 若取不到汉堡，要和服务生打交道
					try {
						System.out.println("### Customer: waiter.wait():"
								+ " Sorry, Sir, there is no hambergs left, please wait!");
						System.out.println(Thread.currentThread().getName() + ": OK, Waiting for new hambergs");
						// 服务生安抚顾客，让他等待。
						waiter.wait();
						continue;
					} catch (InterruptedException ex) {
						ex.printStackTrace();
					}
				}
			}
		}
	}

	private void eatHamberg() {
		try {
			// 吃每个汉堡的时间不等
			sleeptime = Math.abs(r.nextInt(3000)) * 5;
			System.out.println(Thread.currentThread().getName() + ": I'm eating the hamberg for " + sleeptime
					+ " milliseconds");

			Thread.sleep(sleeptime);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void getHamberg() throws Exception {
		Hamberg hamberg = null;

		synchronized (pool) {
			try {
				// 在容器内取汉堡
				hamberg = pool.pop();

				ateCount++;
				System.out
						.println(Thread.currentThread().getName() + ": I Got " + ateCount + " Hamberg " + hamberg);
				System.out.println(Thread.currentThread().getName() + ": There are still " + pool.size()
						+ " hambergs left");

			} catch (Exception e) {
				pool.notifyAll();
				System.out.println("### Customer: pool.notifyAll()");
				throw new Exception(Thread.currentThread().getName()
						+ ": OH MY GOD!!!! No hambergs left, Waiter![Ring the bell besides the hamberg pool]");

			}
		}
	}
}
